package com.iotechn.unimall.admin.api.purchasereturnorder;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.iotechn.unimall.biz.service.goods.GoodsBizService;
import com.iotechn.unimall.core.exception.AdminServiceException;
import com.iotechn.unimall.core.exception.ExceptionDefinition;
import com.iotechn.unimall.core.exception.ServiceException;
import com.iotechn.unimall.core.exception.ServiceExceptionDefinition;
import com.iotechn.unimall.data.domain.*;
import com.iotechn.unimall.data.dto.AdminDTO;
import com.iotechn.unimall.data.dto.warehouse.PurchaseWarehouseOrderGoodsDTO;
import com.iotechn.unimall.data.mapper.*;
import com.iotechn.unimall.data.model.Page;
import com.iotechn.unimall.data.util.SessionUtil;
import org.apache.ibatis.session.RowBounds;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 后台退货/退库管理
 *
 * @author kyms
 * @date 2020-07-15 10:18
 */
@Service
public class AdminPurchaseReturnOrderServiceImpl implements AdminPurchaseReturnOrderService {
    private static final Logger LOGGER = LoggerFactory.getLogger(AdminPurchaseReturnOrderServiceImpl.class);
    private final static String STORE_STOCK_RETURN_PRE = "TH";
    @Autowired
    private PurchaseOrderReturnMapper purchaseOrderReturnMapper;
    @Autowired
    private PurchaseOrderReturnGoodsMapper purchaseOrderReturnGoodsMapper;
    @Autowired
    private PurchaseOrderReturnOperLogMapper purchaseOrderReturnOperLogMapper;
    @Autowired
    private WarehouseMapper warehouseMapper;
    @Autowired
    private SupplierMapper supplierMapper;
    @Autowired
    private StoreMapper storeMapper;
    @Autowired
    private GoodsBizService goodsBizService;
    @Autowired
    private WarehouseGoodsMapper warehouseGoodsMapper;
    @Autowired
    private SkuMapper skuMapper;
    @Autowired
    private SpuMapper spuMapper;
    @Autowired
    private WarehouseOperLogMapper warehouseOperLogMapper;
    @Autowired
    private FinancePayableMapper financePayableMapper;

    @Override
    public Page<PurchaseOrderReturnDO> page(Integer page, Integer limit, String search, String skuSearch, Integer storeOrderState, String timeRange, Long customerId, Integer customerType, Long userId) throws ServiceException {
        Wrapper<PurchaseOrderReturnDO> wrapper = new EntityWrapper<PurchaseOrderReturnDO>();
        if (customerId == null || customerId <= 0) {
        }
        wrapper.eq(customerId != null && customerId > 0L, "customer_id", customerId);
        if (!StringUtils.isEmpty(search)) {
            wrapper.like("order_no", search);
        }
        wrapper.eq(customerType != null, "customer_type", customerType);
        if (!StringUtils.isEmpty(timeRange)) {
            String[] times = timeRange.split(",");
            wrapper.between("gmt_create", times[0], times[1]);
        }
        if (storeOrderState != null) {
            wrapper.eq("order_return_state", storeOrderState);
        }
        List<Integer
                > orderIds = new LinkedList<>();
        if (!StringUtils.isEmpty(skuSearch)) {
            List<PurchaseOrderReturnGoodsDO> orderSkus = purchaseOrderReturnGoodsMapper.selectList(new EntityWrapper<PurchaseOrderReturnGoodsDO>()
                    .like("bar_code", skuSearch).or().like("spu_name", skuSearch).or().like("sku_name", skuSearch));

            if (org.springframework.util.CollectionUtils.isEmpty(orderSkus)) {
                return new Page<>(new ArrayList<>(), page, limit, 0L);
            }
            orderIds = orderSkus.stream().map(PurchaseOrderReturnGoodsDO::getOrderReturnId).distinct().collect(Collectors.toList());
            wrapper.in(!org.springframework.util.CollectionUtils.isEmpty(orderIds), "id", orderIds);
        }
        wrapper.orderBy("id", false);
        Integer count = purchaseOrderReturnMapper.selectCount(wrapper);
        List<PurchaseOrderReturnDO> purchaseOrderReturns = purchaseOrderReturnMapper.selectPage(new RowBounds((page - 1) * limit, limit), wrapper);
        return new Page<>(purchaseOrderReturns, page, limit, count);
    }


    @Override
    public Page pageSkusBySupplierIdWithPrice(Integer page, Integer limit, String categoryIds, String search, Long supplierId, Long warehouseId, Long userId) throws ServiceException {
        Integer start = (page - 1) * limit;
        Integer end = limit;
        List<PurchaseWarehouseOrderGoodsDTO> purchaseWarehouseOrderGoodsDTOS = purchaseOrderReturnGoodsMapper.listGoodsReturnSupplier(warehouseId,search);
        Integer count = purchaseOrderReturnGoodsMapper.countListGoodsBySupplierId(supplierId, warehouseId, search);
        return new Page<>(purchaseWarehouseOrderGoodsDTOS, page, limit, count);
    }


    //增加仓库商品数量
    private void returnWarehouseGoodsStock(Long skuId, String barCode, Float goodsNum, String orderNo, Long orderId, Long warehouseId, Integer goodsEntryType, PurchaseOrderReturnGoodsDO purchaseOrderReturnGoodsDO) throws AdminServiceException {
        AdminDTO adminDTO = SessionUtil.getAdmin();
        Date now = new Date();
        WarehouseDO mainWarehouse = warehouseMapper.selectById(warehouseId);
        WarehouseGoodsDO updateWarehouseGoodsDo = new WarehouseGoodsDO();
        updateWarehouseGoodsDo.setWarehouseId(warehouseId);
        updateWarehouseGoodsDo.setSkuId(skuId);
        // updateWarehouseGoodsDo.setSkuBarCode(barCode);
        WarehouseGoodsDO warehouseGoodsDO = warehouseGoodsMapper.selectOne(updateWarehouseGoodsDo);
        WarehouseGoodsDO origWarehouseGoodsDO = new WarehouseGoodsDO();
        BeanUtils.copyProperties(warehouseGoodsDO,origWarehouseGoodsDO);
        if (warehouseGoodsDO != null) {
            Float stock = warehouseGoodsDO.getWarehouseSkuStock() + goodsNum;
            if (stock > 0) {
                warehouseGoodsDO.setWarehouseSkuStock(stock);
                warehouseGoodsDO.setGmtUpdate(now);
                warehouseGoodsMapper.updateById(warehouseGoodsDO);
                Integer integer = addSkuStock(skuId, goodsNum);
                if(goodsNum < 0){
                    throw new AdminServiceException(new ServiceExceptionDefinition(13025, "条码:" + barCode + " 商品库存修改异常～"));
                }
            }
        } else {
            warehouseGoodsDO = new WarehouseGoodsDO();
            warehouseGoodsDO.setWarehouseSkuStock(goodsNum);
            warehouseGoodsDO.setSkuBarCode(barCode);
            warehouseGoodsDO.setWarehouseId(warehouseId);
            warehouseGoodsDO.setAllprice(purchaseOrderReturnGoodsDO.getGoodsPrice());
            warehouseGoodsDO.setGoodsHistoryAmount(purchaseOrderReturnGoodsDO.getGoodsReturnNum());
            warehouseGoodsDO.setSpuId(purchaseOrderReturnGoodsDO.getSpuId().longValue());
            warehouseGoodsDO.setSkuId(purchaseOrderReturnGoodsDO.getSkuId());
            warehouseGoodsDO.setImg(purchaseOrderReturnGoodsDO.getGoodsImg());
            warehouseGoodsDO.setUnit(purchaseOrderReturnGoodsDO.getGoodsUnit());
            warehouseGoodsDO.setTitle(purchaseOrderReturnGoodsDO.getSpuName() + " " + purchaseOrderReturnGoodsDO.getSkuName());
            warehouseGoodsDO.setPrice(purchaseOrderReturnGoodsDO.getGoodsPrice());
            warehouseGoodsDO.setAdminId(adminDTO.getId());
            warehouseGoodsDO.setGmtCreate(now);
            warehouseGoodsDO.setGmtUpdate(now);
            warehouseGoodsMapper.insert(warehouseGoodsDO);
            Integer integer = addSkuStock(skuId, goodsNum);
            if(goodsNum < 1){
                throw new AdminServiceException(new ServiceExceptionDefinition(13025, "条码:" + barCode + " 商品库存修改异常～"));
            }
        }
        //插入仓库-操作记录
        this.insertWarehouseGoodLog(origWarehouseGoodsDO,warehouseGoodsDO, goodsNum, goodsEntryType, orderNo, orderId);
        LOGGER.info("barCode:{},goodsNum:{},warehouseName:{},warehouseId:{}", barCode, goodsNum, mainWarehouse.getWarehouseName(), mainWarehouse.getId());
    }


    //插入仓库-商品记录
    private void insertWarehouseGoodLog(WarehouseGoodsDO origWarehouseGoodsDO, WarehouseGoodsDO warehouseGoodsDO, Float num, Integer type, String orderNo, Long orderId) {
        WarehouseOperLogDO warehouseOperLogDO = new WarehouseOperLogDO();
        Date now = new Date();
        warehouseOperLogDO.setGmtCreate(now);
        warehouseOperLogDO.setGmtUpdate(now);
        warehouseOperLogDO.setChangeSkuStock(num);
        AdminDTO adminDTO = SessionUtil.getAdmin();
        if (adminDTO != null) {
            warehouseOperLogDO.setAdminId(adminDTO.getId());
            warehouseOperLogDO.setAdminName(adminDTO.getRealname());
        }
        warehouseOperLogDO.setSkuId(warehouseGoodsDO.getSkuId());
        warehouseOperLogDO.setType(type);
        warehouseOperLogDO.setWarehouseSkuStock(warehouseGoodsDO.getWarehouseSkuStock());
        warehouseOperLogDO.setWarehouseId(warehouseGoodsDO.getWarehouseId());
        warehouseOperLogDO.setWarehouseName(warehouseGoodsDO.getWarehouseName());
        warehouseOperLogDO.setSkuNo(warehouseGoodsDO.getSkuBarCode());
        warehouseOperLogDO.setOrderNo(orderNo);
        warehouseOperLogDO.setOrderId(orderId);
        warehouseOperLogDO.setOrigSkuStock(origWarehouseGoodsDO.getWarehouseSkuStock());
        warehouseOperLogDO.setOrigAvgPrice(origWarehouseGoodsDO.getPrice().intValue());
        warehouseOperLogDO.setCurrAvgPrice(warehouseGoodsDO.getPrice().intValue());
        SkuDO skuQuery = new SkuDO();
        skuQuery.setBarCode(warehouseGoodsDO.getSkuBarCode());
        SkuDO skuDO = skuMapper.selectOne(skuQuery);
        if (skuDO != null) {
            warehouseOperLogDO.setSkuName(skuDO.getTitle());
        }
        warehouseOperLogDO.setSkuId(warehouseGoodsDO.getSkuId());
        warehouseOperLogDO.setSpuId(warehouseGoodsDO.getSpuId());
        if (warehouseGoodsDO.getSpuId() != null) {
            SpuDO spu = spuMapper.selectById(warehouseGoodsDO.getSpuId());
            if (spu != null) {
                warehouseOperLogDO.setSpuName(spu.getTitle());

            }
        }
        warehouseOperLogMapper.insert(warehouseOperLogDO);
    }


    //从仓库商品中减少数量
    private void decWarehouseGoodsStock(Long skuId, String barCode, Float goodsNum, String orderNo, Long orderId, Long warehouseId, Integer goodsEntryType) throws ServiceException {
        WarehouseGoodsDO updateWarehouseGoodsDo = new WarehouseGoodsDO();
        updateWarehouseGoodsDo.setWarehouseId(warehouseId);
        updateWarehouseGoodsDo.setSkuId(skuId);
        // updateWarehouseGoodsDo.setSkuBarCode(barCode);
        WarehouseGoodsDO warehouseGoodsDO = warehouseGoodsMapper.selectOne(updateWarehouseGoodsDo);
        WarehouseGoodsDO origWarehouseGoodsDO = new WarehouseGoodsDO();
        BeanUtils.copyProperties(warehouseGoodsDO,origWarehouseGoodsDO);
        Date now = new Date();
        if (warehouseGoodsDO != null) {
            Float stock = warehouseGoodsDO.getWarehouseSkuStock() - goodsNum;
            if (stock >= 0) {
                warehouseGoodsDO.setWarehouseSkuStock(stock);
                warehouseGoodsDO.setGmtUpdate(now);
                warehouseGoodsMapper.updateById(warehouseGoodsDO);
                SkuDO skuQuery = new SkuDO();
                //   skuQuery.setBarCode(barCode);
                skuQuery.setId(skuId);
                SkuDO skuDO = skuMapper.selectOne(skuQuery);
                if (skuDO != null) {
                    Float skuStock = skuDO.getStock();
                    skuStock = skuStock - goodsNum;
                    if (skuStock != null) {
                        skuDO.setGmtUpdate(now);
                        skuDO.setStock(skuStock);
                        skuDO.setGmtUpdate(now);
                        skuMapper.updateById(skuDO);
                    } else {
                        LOGGER.error("[后台库存减少失败]barCode:{},stock,{},warehouseId:{},goodsNum:{},orderId,{}", barCode, stock, warehouseId, goodsNum, orderId);
                        throw new AdminServiceException(new ServiceExceptionDefinition(13025, "条码:" + barCode + " 商品库存不足～"));
                    }
                } else{
                    LOGGER.error("[后台库存减少失败]barCode:{},stock,{},warehouseId:{},goodsNum:{},orderId,{}", barCode, stock, warehouseId, goodsNum, orderId);
                    throw new AdminServiceException(new ServiceExceptionDefinition(13025, "条码:" + barCode + " 商品库存不不存在～"));
                }
                //插入仓库-操作记录
                this.insertWarehouseGoodLog(origWarehouseGoodsDO,warehouseGoodsDO, goodsNum, goodsEntryType, orderNo, orderId);
            } else {
                LOGGER.error("[后台库存减少失败]barCode:{},stock,{},warehouseId:{},goodsNum:{},orderId,{}", barCode, stock, warehouseId, goodsNum, orderId);
                //throw new AdminServiceException(ExceptionDefinition.ORDER_SKU_STOCK_NOT_ENOUGH_V2);
                throw new AdminServiceException(new ServiceExceptionDefinition(13025, "条码:" + barCode + " 商品库存不足～"));
            }
        }

    }


    /**
     * 退库至供应商  从仓库商品中减少数量
     * @param skuId
     * @param barCode
     * @param goodsNum
     * @param orderNo
     * @param orderId
     * @param warehouseId
     * @param goodsEntryType
     * @throws ServiceException
     */
    private void decWarehouseGoodsStockV2(Long skuId, String barCode, Float goodsNum, String orderNo, Long orderId, Long warehouseId, Integer goodsEntryType) throws ServiceException {
        SkuDO skuDO = skuMapper.selectById(skuId);
            returnSupplierWarehouseGoods(warehouseId,
                    skuId,
                    goodsNum,
                    barCode,
                    goodsEntryType,
                    orderNo,
                    orderId);



    }

    public void returnSupplierWarehouseGoods(Long warehouseId,
                                             Long skuId,
                                             Float goodsNum,
                                             String barCode,
                                             Integer goodsEntryType,
                                             String orderNo,
                                             Long orderId) throws AdminServiceException {
        WarehouseGoodsDO updateWarehouseGoodsDo = new WarehouseGoodsDO();
        updateWarehouseGoodsDo.setWarehouseId(warehouseId);
        updateWarehouseGoodsDo.setSkuId(skuId);
        WarehouseGoodsDO warehouseGoodsDO = warehouseGoodsMapper.selectOne(updateWarehouseGoodsDo);
        WarehouseGoodsDO origWarehouseGoodsDO = new WarehouseGoodsDO();
        BeanUtils.copyProperties(warehouseGoodsDO,origWarehouseGoodsDO);
        Date now = new Date();
        if (warehouseGoodsDO != null) {
            Float stock = warehouseGoodsDO.getWarehouseSkuStock() - goodsNum;
            if (stock >= 0) {
                warehouseGoodsDO.setWarehouseSkuStock(stock);
                warehouseGoodsDO.setGmtUpdate(now);
                warehouseGoodsMapper.updateById(warehouseGoodsDO);
                SkuDO skuQuery = new SkuDO();
                //   skuQuery.setBarCode(barCode);
                skuQuery.setId(skuId);
                SkuDO skuDO = skuMapper.selectOne(skuQuery);
                if (skuDO != null) {
                    Float skuStock = skuDO.getStock();
                    skuStock = skuStock - goodsNum;
                    if (skuStock >= 0) {
                        skuDO.setGmtUpdate(now);
                        skuDO.setStock(skuStock);
                        skuDO.setGmtUpdate(now);
                        skuMapper.updateById(skuDO);
                    } else {
                        LOGGER.error("[后台库存减少失败]barCode:{},stock,{},warehouseId:{},goodsNum:{},orderId,{}", barCode, stock, warehouseId, goodsNum, orderId);
                        throw new AdminServiceException(new ServiceExceptionDefinition(13025, "条码:" + barCode + " 商品库存不足～"));
                    }
                } else{
                    LOGGER.error("[后台库存减少失败]barCode:{},stock,{},warehouseId:{},goodsNum:{},orderId,{}", barCode, stock, warehouseId, goodsNum, orderId);
                    throw new AdminServiceException(new ServiceExceptionDefinition(13025, "条码:" + barCode + " 商品库存不不存在～"));
                }
                //插入仓库-操作记录
                this.insertWarehouseGoodLog(origWarehouseGoodsDO,warehouseGoodsDO, goodsNum, goodsEntryType, orderNo, orderId);
            } else {
                LOGGER.error("[后台库存减少失败]barCode:{},stock,{},warehouseId:{},goodsNum:{},orderId,{}", barCode, stock, warehouseId, goodsNum, orderId);
                //throw new AdminServiceException(ExceptionDefinition.ORDER_SKU_STOCK_NOT_ENOUGH_V2);
                throw new AdminServiceException(new ServiceExceptionDefinition(13025, "条码:" + barCode + " 商品库存不足～"));
            }
        }
    }

    /**
     * 增加sku 库存
     * @param skuId
     * @param goodsNum
     * @return
     */
    public Integer addSkuStock(Long skuId,Float goodsNum){
        Date now = new Date();
        SkuDO skuQuery = new SkuDO();
        skuQuery.setId(skuId);
        SkuDO skuDO = skuMapper.selectOne(skuQuery);
        if (skuDO != null) {
            Float skuStock = skuDO.getStock();
            skuStock = skuStock + goodsNum;
            skuDO.setGmtUpdate(now);
            skuDO.setStock(skuStock);
            skuDO.setGmtUpdate(now);
            return skuMapper.updateById(skuDO);
        }
        if(skuDO != null){
            return 0;
        }
        return 0;
    }

}
